import base64
import pickle

from django import http
from pprint import pprint

from django.core.paginator import Paginator, EmptyPage
from django.http import HttpResponseNotFound, JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import GoodsCategory, SKU
from apps.goods.utils import get_categories, get_breadcrumb
from utils import constants
from utils.response_code import RETCODE


class ListView(View):
    """商品列表页"""

    def get(self, request, category_id, page_num):
        """提供商品列表页"""
        # 判断category_id是否正确
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return HttpResponseNotFound('GoodsCategory does not exist')

        # 查询商品频道分类
        categories = get_categories()
        # 查询面包屑导航
        breadcrumb = get_breadcrumb(category)

        # 获取商品分类
        categories = get_categories()

        # 接收sort参数：如果用户不传，就是默认的排序规则
        sort = request.GET.get('sort', 'default')

        # 按照排序规则查询该分类商品SKU信息
        if sort == 'price':
            # 按照价格由低到高
            sort_field = 'price'
        elif sort == 'hot':
            # 按照销量由高到低
            sort_field = '-sales'
        else:
            # 'price'和'sales'以外的所有排序方式都归为'default'
            sort = 'default'
            sort_field = 'create_time'

        skus = SKU.objects.filter(spu__category3=category, is_launched=True).order_by(sort_field)

        # 创建分页器：每页N条记录
        paginator = Paginator(skus, constants.GOODS_LIST_LIMIT)
        # 获取每页商品数据
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            # 如果page_num不正确，默认给用户404
            return http.HttpResponseNotFound('empty page')
        # 获取列表页总页数
        total_page = paginator.num_pages

        # 判断用户是否登录
        user = request.user
        print(user)
        if user.is_authenticated:
            # 用户已登录，查询Redis购物车
            redis_conn = get_redis_connection('carts')
            redis_cart = redis_conn.hgetall('carts_%s' % user.id)
            cart_selected = redis_conn.smembers('selected_%s' % user.id)
            # 将redis中的两个数据统一格式，跟cookie中的格式一致，方便统一查询
            cart_dict = {}
            for sku_id, count in redis_cart.items():
                cart_dict[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in cart_selected
                }
        else:
            # 用户未登录，查询cookie购物车
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart_dict = {}

        # 构造简单购物车JSON数据
        cart_skus = []
        sku_ids = cart_dict.keys()
        skus = SKU.objects.filter(id__in=sku_ids)
        for sku in skus:
            cart_skus.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'count': cart_dict.get(sku.id).get('count'),
                'default_image_url': sku.default_image
            })
        print(cart_skus)
        # print(len(cart_skus))
        num = 0
        num2 = 0
        num3 = list()
        for c in cart_skus:
            # print(c["count"])
            # print(c['price'])
            num1 = c['count']
            price = c['price'] * num1
            num += num1
            num3.append(num1)
            num2 += price
        # print(num)
        # print(num2)
        print(num3)
        # 渲染页面
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'category': category,
            'sort': sort,  # 排序字段
            'page_skus': page_skus,  # 分页后数据
            'total_page': total_page,  # 总页数
            'page_num': page_num,  # 当前页码
            'cart_skus': cart_skus,
            'count': num,
            'price_mall': num2,
            'num3': num3,
        }
        print(page_skus, '222222222222222222')
        print(context)
        for i in page_skus:
            print(i.name)
        return render(request, 'list.html', context=context)


class HotGoodsView(View):
    """商品热销排行"""

    def get(self, request, category_id):
        """提供商品热销排行JSON数据"""
        # 根据销量倒序
        skus = SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]

        # 序列化
        hot_skus = []
        for sku in skus:
            hot_skus.append({
                'id': sku.id,
                'default_image_url': sku.default_image,
                'name': sku.name,
                'price': sku.price
            })

        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': hot_skus})


class DetailView(View):
    """商品详情页"""

    def get(self, request, sku_id):
        """提供商品详情页"""
        # 获取当前sku的信息
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return render(request, '404.html')

        # 查询商品频道分类
        categories = get_categories()

        # 查询面包屑导航
        # category = sku.spu.category3
        category = sku.category
        breadcrumb = get_breadcrumb(category)

        # 取出所有的spu下的sku
        spu_specs_dict = {}
        all_skus = sku.spu.sku_set.all()
        for sku_temp in all_skus:
            one_sku_specs = sku_temp.specs.all()
            for one_sku_spec in one_sku_specs:
                if (one_sku_spec.spec.name, one_sku_spec.option.value) not in spu_specs_dict:
                    spu_specs_dict[(one_sku_spec.spec.name, one_sku_spec.option.value)] = {sku_temp.id}
                else:
                    spu_specs_dict[(one_sku_spec.spec.name, one_sku_spec.option.value)].add(sku_temp.id)

        pprint(spu_specs_dict)
        # demo数据
        # {('内存', '256GB'): {8, 4, 6},
        #  ('内存', '64GB'): {3, 5, 7},
        #  ('颜色', '深空灰'): {5, 6},
        #  ('颜色', '金色'): {3, 4},
        #  ('颜色', '银色'): {8, 7}}

        for op, val in spu_specs_dict.items():
            if sku.id in val:
                set_temp = val - {sku.id}  # 例如 {8, 6}
                spu_specs_dict[op] = {sku.id}  # 例如{4}
                for op_2, val_2 in spu_specs_dict.items():
                    for sku_id in set_temp:
                        if sku_id in val_2:
                            spu_specs_dict[op_2] = {sku_id}

        pprint(spu_specs_dict)
        # demo数据
        # {('内存', '256GB'): {4},
        #  ('内存', '64GB'): {3},
        #  ('颜色', '深空灰'): {6},
        #  ('颜色', '金色'): {4},
        #  ('颜色', '银色'): {8}}

        spu_options = {}
        for op, val in spu_specs_dict.items():
            if op[0] not in spu_options:
                spu_options[op[0]] = [(op[1], val.pop())]
            else:
                spu_options[op[0]].append((op[1], val.pop()))

        pprint(spu_options)
        # demo数据
        # {'内存': [('64GB', 3), ('256GB', 4)], '颜色': [('金色', 4), ('深空灰', 6), ('银色', 8)]}

        # 渲染页面
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'sku': sku,
            'specs': spu_options,
        }

        return render(request, 'detail.html', context)